package qdrant

import (
	"fmt"
	"os"
	"path/filepath"
	"time"

	"gopkg.in/yaml.v3"
)

// Config 包含Qdrant客户端的完整配置
type Config struct {
	// 数据存储路径
	DataPath string `yaml:"data_path" json:"data_path"`
	
	// 连接配置
	Connection ConnectionConfig `yaml:"connection" json:"connection"`
	
	// 集合配置
	Collection CollectionConfigYAML `yaml:"collection" json:"collection"`
	
	// 索引配置
	Index IndexConfig `yaml:"index" json:"index"`
}

// ConnectionConfig 连接相关配置
type ConnectionConfig struct {
	Host           string `yaml:"host" json:"host"`
	Port           int    `yaml:"port" json:"port"`
	MaxConnections int    `yaml:"max_connections" json:"max_connections"`
	Timeout        int    `yaml:"timeout" json:"timeout"` // 秒
	RetryAttempts  int    `yaml:"retry_attempts" json:"retry_attempts"`
	RetryBackoff   string `yaml:"retry_backoff" json:"retry_backoff"`
}

// CollectionConfigYAML 集合配置（YAML格式）
type CollectionConfigYAML struct {
	Name       string `yaml:"name" json:"name"`
	VectorSize int    `yaml:"vector_size" json:"vector_size"`
	Distance   string `yaml:"distance" json:"distance"`
}

// IndexConfig 索引配置
type IndexConfig struct {
	Type        string `yaml:"type" json:"type"`
	M           int    `yaml:"m" json:"m"`
	EfConstruct int    `yaml:"ef_construct" json:"ef_construct"`
}

// ConfigManager 负责管理向量数据库的配置
type ConfigManager struct {
	config *Config
}

// NewConfigManager 创建一个新的配置管理器
func NewConfigManager() *ConfigManager {
	return &ConfigManager{
		config: getDefaultConfig(),
	}
}

// getDefaultConfig 返回默认配置
func getDefaultConfig() *Config {
	return &Config{
		DataPath: "./data_vector",
		Connection: ConnectionConfig{
			Host:           "localhost",
			Port:           6334,
			MaxConnections: 10,
			Timeout:        30,
			RetryAttempts:  3,
			RetryBackoff:   "exponential",
		},
		Collection: CollectionConfigYAML{
			Name:       "documents",
			VectorSize: 1024, // bge-base-zh-v1.5模型的向量维度
			Distance:   "Cosine",
		},
		Index: IndexConfig{
			Type:        "hnsw",
			M:           16,
			EfConstruct: 200,
		},
	}
}

// LoadConfig 从文件加载配置
func (cm *ConfigManager) LoadConfig(configPath string) error {
	if configPath == "" {
		// 使用默认配置
		return nil
	}
	
	// 检查配置文件是否存在
	if _, err := os.Stat(configPath); os.IsNotExist(err) {
		// 配置文件不存在，创建默认配置文件
		return cm.SaveConfig(configPath)
	}
	
	// 读取配置文件
	data, err := os.ReadFile(configPath)
	if err != nil {
		return fmt.Errorf("failed to read config file: %w", err)
	}
	
	// 解析YAML配置
	var config Config
	if err := yaml.Unmarshal(data, &config); err != nil {
		return fmt.Errorf("failed to parse config file: %w", err)
	}
	
	// 验证配置
	if err := cm.validateConfig(&config); err != nil {
		return fmt.Errorf("invalid config: %w", err)
	}
	
	cm.config = &config
	return nil
}

// SaveConfig 保存配置到文件
func (cm *ConfigManager) SaveConfig(configPath string) error {
	// 确保目录存在
	dir := filepath.Dir(configPath)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return fmt.Errorf("failed to create config directory: %w", err)
	}
	
	// 序列化配置
	data, err := yaml.Marshal(cm.config)
	if err != nil {
		return fmt.Errorf("failed to marshal config: %w", err)
	}
	
	// 写入文件
	if err := os.WriteFile(configPath, data, 0644); err != nil {
		return fmt.Errorf("failed to write config file: %w", err)
	}
	
	return nil
}

// GetConfig 获取当前配置
func (cm *ConfigManager) GetConfig() *Config {
	return cm.config
}

// SetDataPath 设置数据路径
func (cm *ConfigManager) SetDataPath(path string) error {
	if path == "" {
		return fmt.Errorf("data path cannot be empty")
	}
	
	// 验证路径
	if err := cm.validatePath(path); err != nil {
		return err
	}
	
	cm.config.DataPath = path
	return nil
}

// GetVectorDBPath 确定向量库的存储路径
func (cm *ConfigManager) GetVectorDBPath(customPath string, kbPath string) (string, error) {
	// 如果提供了自定义路径，直接使用
	if customPath != "" {
		if err := cm.validatePath(customPath); err != nil {
			return "", fmt.Errorf("invalid custom path: %w", err)
		}
		return customPath, nil
	}
	
	// 如果配置中有路径，使用配置路径
	if cm.config.DataPath != "" && cm.config.DataPath != "./data_vector" {
		return cm.config.DataPath, nil
	}
	
	// 生成默认路径
	return cm.generateDefaultPath(kbPath)
}

// generateDefaultPath 生成默认向量库路径
func (cm *ConfigManager) generateDefaultPath(kbPath string) (string, error) {
	if kbPath == "" {
		// 使用当前目录
		currentDir, err := os.Getwd()
		if err != nil {
			return "", fmt.Errorf("failed to get current directory: %w", err)
		}
		kbPath = currentDir
	}
	
	// 生成默认路径：[知识库目录]_vector
	kbDir := filepath.Base(kbPath)
	parentDir := filepath.Dir(kbPath)
	defaultPath := filepath.Join(parentDir, kbDir+"_vector")
	
	// 确保路径存在
	if err := os.MkdirAll(defaultPath, 0755); err != nil {
		return "", fmt.Errorf("failed to create default vector path: %w", err)
	}
	
	return defaultPath, nil
}

// validatePath 验证路径的有效性
func (cm *ConfigManager) validatePath(path string) error {
	// 检查路径是否为绝对路径或相对路径
	if !filepath.IsAbs(path) && !filepath.IsLocal(path) {
		return fmt.Errorf("invalid path format: %s", path)
	}
	
	// 尝试创建目录
	if err := os.MkdirAll(path, 0755); err != nil {
		return fmt.Errorf("cannot create directory: %w", err)
	}
	
	// 检查写权限
	testFile := filepath.Join(path, ".write_test")
	file, err := os.Create(testFile)
	if err != nil {
		return fmt.Errorf("no write permission: %w", err)
	}
	file.Close()
	os.Remove(testFile)
	
	return nil
}

// validateConfig 验证配置的有效性
func (cm *ConfigManager) validateConfig(config *Config) error {
	// 验证连接配置
	if config.Connection.Port <= 0 || config.Connection.Port > 65535 {
		return fmt.Errorf("invalid port: %d", config.Connection.Port)
	}
	
	if config.Connection.MaxConnections <= 0 {
		return fmt.Errorf("max_connections must be positive")
	}
	
	if config.Connection.Timeout <= 0 {
		return fmt.Errorf("timeout must be positive")
	}
	
	// 验证集合配置
	if config.Collection.Name == "" {
		return fmt.Errorf("collection name cannot be empty")
	}
	
	if config.Collection.VectorSize <= 0 {
		return fmt.Errorf("vector_size must be positive")
	}
	
	validDistances := map[string]bool{
		"Cosine":    true,
		"Euclidean": true,
		"Dot":       true,
	}
	if !validDistances[config.Collection.Distance] {
		return fmt.Errorf("invalid distance metric: %s", config.Collection.Distance)
	}
	
	// 验证索引配置
	if config.Index.M <= 0 {
		return fmt.Errorf("index M must be positive")
	}
	
	if config.Index.EfConstruct <= 0 {
		return fmt.Errorf("ef_construct must be positive")
	}
	
	return nil
}

// UpdateFromCommandLine 从命令行参数更新配置
func (cm *ConfigManager) UpdateFromCommandLine(args map[string]interface{}) error {
	if vecPath, ok := args["vec-path"].(string); ok && vecPath != "" {
		if err := cm.SetDataPath(vecPath); err != nil {
			return fmt.Errorf("invalid vec-path: %w", err)
		}
	}
	
	if collection, ok := args["vec-collection"].(string); ok && collection != "" {
		cm.config.Collection.Name = collection
	}
	
	if timeout, ok := args["vec-timeout"].(time.Duration); ok && timeout > 0 {
		cm.config.Connection.Timeout = int(timeout.Seconds())
	}
	
	return nil
}

// GetConnectionString 获取连接字符串
func (cm *ConfigManager) GetConnectionString() string {
	return fmt.Sprintf("%s:%d", cm.config.Connection.Host, cm.config.Connection.Port)
}

// PrintConfig 打印当前配置（用于调试）
func (cm *ConfigManager) PrintConfig() {
	fmt.Printf("Qdrant配置:\n")
	fmt.Printf("  数据路径: %s\n", cm.config.DataPath)
	fmt.Printf("  连接地址: %s:%d\n", cm.config.Connection.Host, cm.config.Connection.Port)
	fmt.Printf("  集合名称: %s\n", cm.config.Collection.Name)
	fmt.Printf("  向量维度: %d\n", cm.config.Collection.VectorSize)
	fmt.Printf("  距离度量: %s\n", cm.config.Collection.Distance)
}